﻿namespace Mp3Observer.Model
{
    #region usings

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Windows.Media.Imaging;
    using System.Xml.Serialization;

    #endregion

    /// <summary>
    /// Immutable value types should override Object.Equals to get better performance than the default implementation, which uses reflection
    /// </summary>
    [Serializable]
    public class FileEntity : ICloneable, INotifyPropertyChanged, IEquatable<FileEntity>
    {
        private string path = null;
        [XmlIgnore]
        public string Path
        {
            get
            {
                if (Filename == null || Filename == String.Empty)
                    path = String.Empty;
                else
                    if (Filename == "dummy")
                        path = "dummy";
                    else
                        if (String.IsNullOrEmpty(path))
                            path = Filename.Substring(0, Filename.LastIndexOf('\\'));

                return path;
            }
        }

        // private Guid internalId = Guid.NewGuid();
        public string Artist { get; set; }
        public string Title { get; set; }
        public string Album { get; set; }
        public string Genre { get; set; }
        public string TrackNumber { get; set; }
        public string Comment { get; set; }

        [XmlIgnore]
        public Guid InternalId { get; set; } // { return this.internalId; } }
        public int Id { get; set; }

        public string Filename { get; set; }
        private bool isCurrentPlaying;
        [XmlIgnore]
        public bool IsCurrentPlaying
        {
            get { return this.isCurrentPlaying; }
            set
            {
                this.isCurrentPlaying = value;
                OnPropertyChanged("IsCurrentPlaying");
            }
        }

        public FileEntity()
        {
            this.InternalId = Guid.NewGuid();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            // local copy, thread safe!
            var handler = this.PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
        #region ICloneable Members

        public object Clone()
        {
            var clonedObject = this.MemberwiseClone();
            (clonedObject as FileEntity).InternalId = Guid.NewGuid();
            return clonedObject;
        }

        #endregion

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <exception cref="T:System.NullReferenceException">
        /// The <paramref name="obj"/> parameter is null.
        /// </exception>
        public override bool Equals(object obj)
        {
            FileEntity person = obj as FileEntity; // if this is a struct: = (Person)obj
            return person == null ? false : this.Equals(person);
        }

        public bool Equals(FileEntity other)
        {
            if (Object.ReferenceEquals(other, null))
                return false;
            if (Object.ReferenceEquals(other, this))
                return true;

            //return EqualityComparer<string>.Default.Equals(this.LastName, other.LastName) &&
            //    EqualityComparer<string>.Default.Equals(this.FirstName, other.FirstName) &&
            //    EqualityComparer<string>.Default.Equals(this.MiddleName, other.MiddleName);

            return EqualityComparer<Guid>.Default.Equals(this.InternalId, other.InternalId);

            // return ((this.LastName == other.LastName) && (this.FirstName == other.FirstName) && (this.MiddleName == other.MiddleName));
        }
        public override int GetHashCode()
        {
            int hashCode = 0;
            if (this.InternalId != null) hashCode ^= this.InternalId.GetHashCode();
            //if (this.FirstName != null) hashCode ^= this.FirstName.GetHashCode();
            //if (this.MiddleName != null) hashCode ^= this.MiddleName.GetHashCode();
            return hashCode;
        }


        public string UserUrl { get; set; }
        public int PicCount { get; set; }
        
        [XmlIgnore]
        public BitmapImage Picture { get; set; }
        [XmlIgnore]
        public bool PictureIsLoaded { get; set; }

        public int HeaderPlaytimeSeconds { get; set; }

        public string HeaderMode { get; set; }

        public int HeaderFrequency { get; set; }

        public int HeaderBitRate { get; set; }

        private string _shortFileName;
        [XmlIgnore]
        public string ShortFileName
        {
            get
            {
                if (this.Filename == null || Filename == String.Empty)
                    _shortFileName = String.Empty;
                else
                    if (String.IsNullOrEmpty(_shortFileName))
                    {
                        try
                        {
                            FileInfo fi = new FileInfo(Filename);
                            _shortFileName = fi.Name;
                        }
                        catch (ArgumentException exp)
                        {
                            // Illegal characters in path.
                            // J:\MP3Bernhard\rene\kabarett\maxi böhm\kabarett aus wien\04 milit?risches und nachkriegsmiser.mp3
                            _shortFileName = exp.Message;
                        }
                        catch(PathTooLongException exp)
                        {
                            _shortFileName = exp.Message;
                        }
                    }

                return _shortFileName;
            }
        }
    }
}
